#ifndef __WIZ_UTILS_TASK_TEMPLATE_HPP__SHANHAOBO_19800429__
#define __WIZ_UTILS_TASK_TEMPLATE_HPP__SHANHAOBO_19800429__

#include "../../System/WizLock.hpp"

#include "../Ticker/WizUtilsTicker.hpp"

namespace Wiz
{
    namespace Task
    {
        namespace Base
        {
            template<class ParamT> class Type;
        } /// end of namespace Base

        /// Estimated Time of Execute
        namespace ETE
        {
            template<class ParamT> class Type;
        } /// end of namespace ETE

        /// Attach Deattach of Execute
        namespace ADE
        {
            template<class ParamT> class Type;
        } /// end of namespace ADE

        //////////////////////////////////////////////////////
        namespace Group
        {
            template<class ParamT> class Type;
        }

        namespace Manager
        {
            template<class ParamT> class Type;
        } /// end of namespace Manager

		/// Thread Safe
		namespace SyncMgr
		{
			template<class ParamT> class Type;
		} /// end of namespace SyncMgr
    } /// end of namespace Task
} /// end of namespace Wiz

#endif /*__WIZ_UTILS_TASK_TEMPLATE_HPP__SHANHAOBO_19800429__*/

#if defined(WIZ_TASK_PARAM_COUNT) && (WIZ_TASK_PARAM_COUNT >= 0) && (WIZ_TASK_PARAM_COUNT < 255)

namespace Wiz
{
    namespace Task
    {
        namespace Base
        {
            template<class TimeT WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, class T)>
            class Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))> : protected ::Wiz::Signal::Safe::Object::Type<::Wiz::Void::Type(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>
            {
            protected:
                typedef ::Wiz::Task::Manager::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))> Manager;
                Manager* m_Manager;
            public:
                Type(Manager* Mgr) : m_Manager(Mgr)
                {}
                virtual ~Type()
                {
                    m_Manager = WIZ_NULLPTR;
                }
            public:
                ::Wiz::Void::Type SetManager(Manager* Mgr)
                {
                    m_Manager = Mgr;
                }
                Manager* GetManager()
                {
                    return m_Manager;
                }
            public:
                virtual ::Wiz::Void::Type Request(const TimeT& TM WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T)) = 0;
                virtual ::Wiz::Void::Type Interrupt(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T)) = 0;
            };
        } /// end of namespace Base

		/// Each Tick 
        namespace ETE
        {
            template<class TimeT WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, class T)>
            class Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))> : public ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>
            {
                typedef ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>        tSuper;
            public:
                Type(Manager* Mgr) : tSuper(Mgr)
                {}
                virtual ~Type()
                {
                }
            public:
                virtual ::Wiz::Void::Type Process(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T)) = 0;
            public:
                virtual ::Wiz::Void::Type Request(const TimeT& TM WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))
                {
                    WIZ_ASSERT(::Wiz::IsValidPtr(m_Manager));
                    GetManager()->PushRequest(TM, this, &Type::Process);
                }
                virtual ::Wiz::Void::Type Interrupt(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))
                {
                    WIZ_ASSERT(::Wiz::IsValidPtr(m_Manager));
                    this->Clear();
                }
            };
        } /// end of namespace ETE

		/// Attach Deattach
        namespace ADE
        {
            template<class TimeT WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, class T)>
            class Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))> : public ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>
            {
                typedef ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>        tSuper;
            public:
                Type(Manager* Mgr) : tSuper(Mgr)
                {
                }
                virtual ~Type()
                {
                }
            public:
                virtual ::Wiz::Void::Type Attach(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T)) = 0;
                virtual ::Wiz::Void::Type Deattach(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T)) = 0;
            public:
                virtual ::Wiz::Void::Type Request(const TimeT& TM WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_XY(WIZ_TASK_PARAM_COUNT, T, A))
                {
                    WIZ_ASSERT(::Wiz::IsValidPtr(m_Manager));
                    GetManager()->PushRequest(TM, this, &Type::Deattach);
                    this->Attach(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, A));
                }
                virtual ::Wiz::Void::Type Interrupt(WIZ_ENUM_PARAM_XY(WIZ_TASK_PARAM_COUNT, T, A))
                {
                    WIZ_ASSERT(::Wiz::IsValidPtr(m_Manager));
                    this->Clear();
                    this->Deattach(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, A));
                }
            };
        } /// end of namespace ADE

        namespace Group
        {
            template<class TimeT WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, class T)>
            class Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))> : public ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>
            {
                typedef ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>        tSuper;
                typedef ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>        SubTaskType;
                typedef ::Wiz::Map::Type<TimeT, SubTaskType*>                                                  SubTaskMapType;
            public:
                Type(Manager* Mgr) : tSuper(Mgr)
                {}
                virtual ~Type()
                {
                }
            public:
                virtual ::Wiz::Void::Type Request(const TimeT& TM WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_XY(WIZ_TASK_PARAM_COUNT, T, A))
                {
                    WIZ_ASSERT(::Wiz::IsValidPtr(m_Manager));
                    SubTaskMapType::tForEachIter  FE(m_SubTaskMap);
                    while (FE)
                    {
                        FE->GetValue()->Request(FE->GetIndex() + TM WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, A));
                        FE++;
                    }
                }
                ::Wiz::Void::Type Interrupt(WIZ_ENUM_PARAM_XY(WIZ_TASK_PARAM_COUNT, T, A))
				{
                    WIZ_ASSERT(::Wiz::IsValidPtr(m_Manager));
                    SubTaskMapType::tForEachIter  FE(m_SubTaskMap);
                    while (FE)
                    {
                        FE->GetValue()->Interrupt(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, A));
                        FE++;
                    }
                }
            public:
                ::Wiz::Void::Type AddSubTask(const TimeT& Time, SubTaskType* TSKPtr)
                {
                    WIZ_ASSERT(::Wiz::IsValidPtr(TSKPtr));
                    WIZ_ASSERT(::Wiz::IsValidPtr(m_Manager));
                    TSKPtr->SetManager(m_Manager);
                    m_SubTaskMap.Insert(Time, TSKPtr);
                }
            protected:
                SubTaskMapType  m_SubTaskMap;
            };
        } /// end of namespace Group

        namespace Manager
        {
            template<class TimeT WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, class T)>
            class Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))> : public ::Wiz::Ticker::Object::Type<TimeT>
            {
                typedef Type                                                                                            tThis;
                typedef ::Wiz::Ticker::Object::Type<TimeT>                tSuper;
                typedef ::Wiz::Ticker::Type<TimeT>                        tTicker;
                typedef ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>                    tTask;
                typedef ::Wiz::Signal::Safe::Type<::Wiz::Void::Type(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>         tSignal;
                typedef ::Wiz::Map::Type<TimeT, tSignal>                                                                tTaskContainer;

            public:
                Type(tTicker* TPtr) : tSuper(TPtr)
                {
                };
                virtual ~Type()
                {
                }
            public:
                template<class U>
                ::Wiz::Void::Type PushRequest(const TimeT& Time, const U* TSKPtr, ::Wiz::Void::Type(U::*UFunc)(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T)))
                {
                    const TimeT CurrTime = Time + m_TotalTime;
                    tTaskContainer::tIterator Curr = m_TaskList.Find(CurrTime);
                    if (Curr == m_TaskList.End())
                    {
                        Curr = m_TaskList.Insert(CurrTime, tSignal());
                    }

                    WIZ_ASSERT(Curr != m_TaskList.End());

                    Curr.GetValue().Register(TSKPtr, UFunc);
                }

                ::Wiz::Void::Type Tick(const TimeT& DeltaTime WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_XY(WIZ_TASK_PARAM_COUNT, T, A))
                {
                    tTaskContainer Temp;

                    /////////==================//////////
                    tTaskContainer::tIterator  Curr;
                    tTaskContainer::tForEach   FE(Curr, m_TaskList);
                    while (FE.HasMoreElement())
                    {
                        if (::Wiz::Less(Curr.GetIndex(), m_TotalTime))
                        {
                            Curr.GetValue()(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, A));
                            FE.Erase();
                            continue;
                        }
                        break;
                    }
                    /////////==================//////////
                }
            protected:
                tTaskContainer                m_TaskList;
            };
        } /// end of namespace Manager

        /// Sync
		namespace SyncMgr
		{
			template<class TimeT WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, class T)>
			class Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))> : public ::Wiz::Ticker::Object::Type<TimeT>
			{
				typedef Type                                                                                            tThis;
				typedef ::Wiz::Ticker::Object::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>                tSuper;
				typedef ::Wiz::Ticker::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>                        tTicker;
				typedef ::Wiz::Task::Base::Type<TimeT(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>                    tTask;
				typedef ::Wiz::Signal::Safe::Type<::Wiz::Void::Type(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T))>         tSignal;
				typedef ::Wiz::Map::Type<TimeT, tSignal>                                                                tTaskContainer;

			public:
				Type(tTicker* TPtr) : tSuper(TPtr)
				{
				};
				virtual ~Type()
				{
				}
			public:
				template<class U>
				::Wiz::Void::Type PushRequest(const TimeT& Time, const U* TSKPtr, ::Wiz::Void::Type(U::*UFunc)(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, T)))
				{
					const TimeT CurrTime = Time + m_TotalTime;
					::Wiz::ScopedLock::Type sl(m_TaskLock);
					tTaskContainer::tIterator Curr = m_TaskList.Find(CurrTime);
					if (Curr == m_TaskList.End())
					{
						Curr = m_TaskList.Insert(CurrTime, tSignal());
					}

					WIZ_ASSERT(Curr != m_TaskList.End());

					Curr.GetValue().Register(TSKPtr, UFunc);
				}

				::Wiz::Void::Type Tick(const TimeT& DeltaTime WIZ_COMMA_IF(WIZ_TASK_PARAM_COUNT) WIZ_ENUM_PARAM_XY(WIZ_TASK_PARAM_COUNT, T, A))
				{
					::Wiz::ScopedLock::Type sl(m_TaskLock);
					tTaskContainer Temp;

					/////////==================//////////
					tTaskContainer::tIterator  Curr;
					tTaskContainer::tForEach   FE(Curr, m_TaskList);
					while (FE.HasMoreElement())
					{
						if (::Wiz::Less(Curr.GetIndex(), m_TotalTime))
						{
							Curr.GetValue()(WIZ_ENUM_PARAM_X(WIZ_TASK_PARAM_COUNT, A));
							FE.Erase();
							continue;
						}
						break;
					}
					/////////==================//////////
				}
			protected:
				tTaskContainer                m_TaskList;
				::Wiz::Lock::Type       m_TaskLock;
			};
		} /// end of namespace TSManager
    } /// end of namespace Task
} /// end of namespace Wiz

#endif/* defined(WIZ_TASK_PARAM_COUNT) && (WIZ_TASK_PARAM_COUNT >= 0) && (WIZ_TASK_PARAM_COUNT < 255)*/
